package cn.cj.erp.common.security.security.service;

import cn.cj.erp.bo.system.SysUserBo;
import cn.cj.erp.common.enums.StatusEnum;
import cn.cj.erp.common.exception.ServiceException;
import cn.cj.erp.common.redis.RedisCache;
import cn.cj.erp.common.redis.RedisKeyEnum;
import cn.cj.erp.common.security.security.asyncjob.AsyncFactory;
import cn.cj.erp.common.security.security.context.AuthenticationContextHolder;
import cn.cj.erp.common.security.security.utils.SecurityUtils;
import cn.cj.erp.common.threadpool.AsyncManager;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

/**
 * 登录密码方法
 *
 * @author ruoyi
 */
@Service
public class SysPasswordService {
    @Resource
    private RedisCache redisCache;

    private static final int MAX_RETRY_COUNT = 5;

    private static final int LOCK_TIME = 20;

    /**
     * 校验用户密码（密码是否正确，是否达到锁定次数）
     * @param user 用户类
     */
    public void validate(SysUserBo user) {
        Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
        String username = usernamePasswordAuthenticationToken.getName();
        String password = usernamePasswordAuthenticationToken.getCredentials().toString();

        Integer retryCount = redisCache.get(RedisKeyEnum.LOGIN_ERROR_PASSWORD.getKey(username), Integer.class);
        if (ObjectUtil.isNull(retryCount)) {
            retryCount = 0;
        }

        if (retryCount >= MAX_RETRY_COUNT) {
            AsyncManager.getInstance().execute(AsyncFactory.saveLoginLog(username, StatusEnum.ABNORMAL,
                    String.format("密码输错到达%d次，锁定", MAX_RETRY_COUNT)));
            throw new ServiceException(String.format("密码输错到达%d次，临时锁定", MAX_RETRY_COUNT));
        }

        if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
            retryCount = retryCount + 1;
            AsyncManager.getInstance().execute(AsyncFactory.saveLoginLog(username, StatusEnum.ABNORMAL, "密码错误"));
            redisCache.set(RedisKeyEnum.LOGIN_ERROR_PASSWORD.getKey(username), retryCount, LOCK_TIME * 60);
            throw new ServiceException("密码输错");
        } else {
            unlockPassword(username);
        }
    }

    /**
     * 解除密码锁定
     * @param username 用户名
     */
    public void unlockPassword(String username) {
        if (redisCache.hasKey(RedisKeyEnum.LOGIN_ERROR_PASSWORD.getKey(username))) {
            redisCache.delete(RedisKeyEnum.LOGIN_ERROR_PASSWORD.getKey(username));
        }
    }
}
